// ignore_for_file: constant_identifier_names

import 'dart:convert';
import 'dart:typed_data';

import 'package:crypto/crypto.dart';
import 'package:dio/dio.dart';
import 'package:encrypt/encrypt.dart';
import 'package:tiktokadult/tools_base/debug_log.dart';
import 'package:tiktokadult/hj_utils/global.dart';

import '../../assets_tool/lang.dart';
import '../../config/config.dart';
import '../../hj_utils/text_util.dart';
import 'api_exception.dart';
import 'base_resp_bean.dart';
import 'code.dart';
import 'net_manager.dart';

/// 响应拦截器=>返回数据转换
class HttpRespInterceptor extends InterceptorsWrapper {
  static const String TAG = "HttpRespInterceptor";

  HttpRespInterceptor();

  @override
  void onResponse(
    Response<dynamic> response,
    ResponseInterceptorHandler handler,
  ) {
    // final request = response.requestOptions;
    _generateCurl(response);
    handleResponse(response);
    handler.next(response);
  }

  @override
  void onError(
    DioException err,
    ErrorInterceptorHandler handler,
  ) {
    debugLog('onError: ${err.requestOptions.path} ');
    debugLog('onError: ${err.requestOptions.queryParameters}');
    debugLog('onError: ${err.requestOptions.data}');
    debugLog('onError: ${err.requestOptions.headers}');
    debugLog('err:${err.error}');

    handler.next(err);
  }

  static Future<dynamic> handleResponse(Response response) async {
    if (response.statusCode != 200) {
      return Future.error(ApiException(response.statusCode, "statusCode is not 200"));
    }
    BaseRespBean? baseResp;
    if (response.data is Map) {
      baseResp = BaseRespBean.fromJson(response.data);
    } else if (response.data is String) {
      baseResp = BaseRespBean.fromJson(json.decode(response.data));
    } else {
      return Future.error(ApiException(Code.PARSE_DATE_ERROR, Lang.PARSE_DATE_ERROR));
    }

    netManager.setServerTime(baseResp.time);
    int? code = baseResp.code;
    //业务层判断
    if (code == Code.SUCCESS) {
      dynamic data = baseResp.data;
      if (baseResp.hash ?? false) {
        var decryptData = aesDecryptEx(data, Config.encryptKey);
        data = json.decode(decryptData);
      }
      baseResp.data = data;
    } else if (code == Code.FORCE_UPDATE_VERSION) {
      //需要更新
      baseResp.msg = "您的版本需要更新了";
      await handleVer(baseResp.data);
    } else if (code == Code.ACCOUNT_INVISIBLE) {
      //账户被封禁了
      baseResp.msg = "您的账号已被封禁了";
      dynamic data = baseResp.data;
      if (baseResp.hash ?? false) {
        var decryptData = aesDecryptEx(data, Config.encryptKey);
        data = json.decode(decryptData);
      }
      baseResp.data = data;
    } else if (code == Code.TOKEN_ABNORMAL) {
      //token异常
      baseResp.msg = "token异常";
    } else if (code == Code.VERIFY_CODE_REPEAT) {
      //验证码频繁异常
      baseResp.msg = "获取验证码过于频繁";
    } else {
      // unknow code
      baseResp.data = null;
    }

    /// 展示提示
    if (code != Code.SUCCESS) {
      if (TextUtil.isEmpty(baseResp.msg) && TextUtil.isEmpty(baseResp.tip) && response.statusCode != 200) {
        showToast("服务器错误");
      } else {
        if (!TextUtil.isEmpty(baseResp.tip)) {
          showToast(baseResp.tip ?? "");
        } else {
          showToast(baseResp.msg ?? '');
        }
      }
    }
    debugLog('path:${response.requestOptions.baseUrl}${response.requestOptions.path}');
    debugLog('param: ${response.requestOptions.queryParameters}');
    debugLog('data: ${response.requestOptions.data}');
    debugLog('head: ${response.requestOptions.headers}');
    debugLog('resp:${response.data}');
    if (code == Code.SUCCESS) {
      response.data = baseResp.data;
    } else {
      if (baseResp.code != null) {
        response.statusCode = baseResp.code;
        if (baseResp.tip?.isNotEmpty == true) {
          response.statusMessage = baseResp.tip;
        } else if (baseResp.msg?.isNotEmpty == true) {
          response.statusMessage = baseResp.msg;
        }
      }
    }
  }
}

dynamic aesAndJsonDecode(String cipherText) {
  if (TextUtil.isEmpty(cipherText)) return "";
  Uint8List bytes = base64Decode(cipherText);
  String keyTail = String.fromCharCodes(bytes, bytes.length - 6);
  final key = Key.fromUtf8(Config.encryptKey + keyTail);
  final iv = IV.fromUtf8(Config.encryptKey + keyTail);
  Uint8List dst = bytes.sublist(0, bytes.length - 6);
  final encrypt = Encrypter(AES(key, mode: AESMode.cbc));
  final decrypted = encrypt.decryptBytes(Encrypted(dst), iv: iv);
  String decryptData = _utf8decoder.convert(decrypted);
  return json.decode(decryptData);
}

Utf8Decoder _utf8decoder = const Utf8Decoder();

///aes解密
String decrypt(String cipherText) {
  if (TextUtil.isEmpty(cipherText)) return "";
  Uint8List bytes = base64Decode(cipherText);
  String keyTail = String.fromCharCodes(bytes, bytes.length - 6);
  final key = Key.fromUtf8(Config.encryptKey + keyTail);
  final iv = IV.fromUtf8(Config.encryptKey + keyTail);
  Uint8List dst = bytes.sublist(0, bytes.length - 6);
  final encrypt = Encrypter(AES(key, mode: AESMode.cbc));
  final decrypted = encrypt.decryptBytes(Encrypted(dst), iv: iv);
  return _utf8decoder.convert(decrypted);
}

/// 新版本解密
String aesDecryptEx(String cipher, String key) {
  // final t1 = DateTime.now();
  const nonceLen = 12;
  final cipherBytes = base64Decode(cipher);
  final nonce = cipherBytes.sublist(0, nonceLen);
  final largeShaRaw = [...utf8.encode(key), ...nonce];
  final largeShaRawMid = largeShaRaw.length ~/ 2;
  final msgKeyLarge = sha256.convert(largeShaRaw).bytes;
  final msgKey = msgKeyLarge.sublist(8, 24);

  final shaRawA = [...msgKey, ...largeShaRaw.sublist(0, largeShaRawMid)];
  final sha256a = sha256.convert(shaRawA).bytes;

  final shaRawB = [...largeShaRaw.sublist(largeShaRawMid), ...msgKey];
  final sha256b = sha256.convert(shaRawB).bytes;

  final aesKey = [...sha256a.sublist(0, 8), ...sha256b.sublist(8, 24), ...sha256a.sublist(24)];

  final aesIV = [...sha256b.sublist(0, 4), ...sha256a.sublist(12, 20), ...sha256b.sublist(28)];

  final encrypter = Encrypter(AES(Key(Uint8List.fromList(aesKey)), mode: AESMode.cbc));
  final decrypted = encrypter.decryptBytes(Encrypted(cipherBytes.sublist(nonceLen)), iv: IV(Uint8List.fromList(aesIV)));
  final text = const Utf8Decoder().convert(decrypted);
  return text;
}

///存储更新信息
handleVer(Map<String, dynamic> map) async {
  List<dynamic> list = [];
  list.add(map["data"]);
  // lightKV.setString(StoreKeys.UPDATE_INFO, convert.jsonEncode(list));
  // DialogGlobal.instance.openUpdateVersionDialog();
}

_generateCurl(Response res) {
  final options = res.requestOptions;
  const String curl = 'curl -X ';
  final String method = options.method;
  String url = options.baseUrl + options.path;
  String query = '';

  if (options.data != null && options.data is String) {
    query = options.data;
  } else {
    late Map<String, dynamic> map;

    if (options.queryParameters.isNotEmpty) {
      map = options.queryParameters;
    } else if (options.data is Map) {
      map = options.data;
    } else if (options.data is String) {
    } else if (options.data is FormData) {
      map = {};
      map.addEntries((options.data as FormData).fields);
    } else {
      map = {};
    }
    query = Transformer.urlEncodeMap(map);
  }
  String curlUrl;
  if (method.toLowerCase() == 'get') {
    if (query.isNotEmpty) {
      url += (url.contains('?') ? '&' : '?') + query;
    }
    String header = '';
    options.headers.forEach((key, value) {
      if (key != 'content-length') {
        header += ' -H ' '\"$key:$value\" ';
      }
    });

    curlUrl = '$curl$method $header \"$url\"';
  } else {
    String header = '';
    options.headers.forEach((key, value) {
      if (key != 'content-length') {
        header += ' -H ' '\"$key:$value\" ';
      }
    });
    final param = json.encode(options.data).replaceAll('"', '\\"');
    header += " -d \"$param\"";
    curlUrl = '$curl$method $header \"$url\"';
  }

  debugLog('curl ====== $curlUrl');
}
